package logic

import (
	"context"
	"strings"

	"mall/common/enumx"
	"mall/common/modelx"
	"mall/common/mqueuex"
	"mall/common/resultx"
	"mall/service/order/model"
	"mall/service/order/rpc/internal/svc"
	"mall/service/order/rpc/types/order"

	"github.com/zeromicro/go-zero/core/logx"
)

type DetailLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DetailLogic {
	return &DetailLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *DetailLogic) Detail(in *order.DetailRequest) (*order.DetailResponse, error) {
	sn := strings.TrimSpace(in.Sn)
	if in.Id == 0 && len(sn) == 0 && len(in.Filter) == 0 {
		return nil, resultx.StatusError(resultx.ORDER_PARAM_INVALID, "")
	}

	if len(strings.TrimSpace(in.Preload)) > 0 {
		return l.filterDetail(in)
	}

	var res *model.Order
	var err error
	if in.Id > 0 {
		res, err = l.svcCtx.Order.FindOne(l.ctx, uint64(in.Id))
		if err != nil {
			if err == model.ErrNotFound {
				return nil, resultx.StatusError(resultx.ORDER_ID_INVALID, "")
			}

			return nil, err
		}
	} else {
		filterMap := make(map[string]map[string][]interface{})
		filterMap[model.OrderColumns.OrderSN] = map[string][]interface{}{
			"equalTo": []interface{}{sn},
		}
		list, _, listErr := l.svcCtx.Order.GetList(l.ctx, model.M{
			"pageSize": uint64(1),
		}, -1, filterMap)
		if listErr != nil {
			return nil, listErr
		}

		if len(list) == 0 {
			return nil, resultx.StatusError(resultx.ORDER_NOT_FOUND, "")
		}

		res = list[0]
	}

	return &order.DetailResponse{
		Id:              int64(res.ID),
		ParentId:        int64(res.ParentID),
		UserId:          int64(res.UserID),
		Buyer:           res.Buyer,
		Sn:              res.OrderSN,
		OrderType:       int32(res.OrderType),
		SourceType:      int32(res.SourceType),
		Quantity:        int32(res.Quantity),
		GemAmount:       int64(res.GemAmount),
		RetailAmount:    int64(res.RetailAmount),
		Freight:         int64(res.Freight),
		DiscountAmount:  int64(res.DiscountAmount),
		AdjustAmount:    int64(res.AdjustAmount),
		ActualAmount:    int64(res.ActualAmount),
		DepositAmount:   int64(res.DepositAmount),
		BalanceAmount:   int64(res.BalanceAmount),
		Amount:          int64(res.RemainingAmount),
		RefundAmount:    int64(res.RefundAmount),
		Gems:            int64(res.Gems),
		TradeState:      int32(res.TradeState),
		DelState:        int32(res.DelState),
		Remark:          res.Remark,
		SellerMemo:      res.SellerMemo,
		CreatedAt:       modelx.FormatTime(res.CreatedAt, ""),
		UpdatedAt:       modelx.FormatTime(res.UpdatedAt, ""),
		DeletedAt:       modelx.FormatNullDotTime(res.DeletedAt, ""),
		PaidAt:          modelx.FormatNullDotTime(res.PaidAt, ""),
		ShippedAt:       modelx.FormatNullDotTime(res.ShippedAt, ""),
		DeliveredAt:     modelx.FormatNullDotTime(res.DeliveredAt, ""),
		ConfirmedAt:     modelx.FormatNullDotTime(res.ConfirmedAt, ""),
		ReviewedAt:      modelx.FormatNullDotTime(res.ReviewedAt, ""),
		FulfilledAt:     modelx.FormatNullDotTime(res.FulfilledAt, ""),
		ClosedAt:        modelx.FormatNullDotTime(res.ClosedAt, ""),
		AutoComfirmDays: int32(res.AutoComfirmDays),
		Comments:        int32(res.Comments),
		Growth:          int32(res.Growth),
		Integrals:       int32(res.Integrals),
	}, nil
}

func (l *DetailLogic) filterDetail(in *order.DetailRequest) (*order.DetailResponse, error) {
	logx.Infof("DetailRequest: %+v ", in)
	// DetailRequest: Sn:\"G2023052519100309626655041\" Preload:\"order:Id,Sn,OrderType,TradeState,Quantity,GemAmount,RetailAmount,Freight,DiscountAmount,AdjustAmount,ActualAmount,Amount,RefundAmount,Gems,TradeState,Remark,CreatedAt,UpdatedAt,PaidAt,ShippedAt,DeliveredAt,ConfirmedAt,ReviewedAt,ClosedAt,Comments,Growth,Integrals;orderItem:Id,Sku,ImageUrl,ProductId,EntryId,Title,Slug,ProductType,BrandId,BrandTitle,BrandSlug,GemPrice,RetailPrice,Quantity,Weight,TradeState,RefundAmount,RefundQuantity;orderAddress:Consignee,Mobile,Province,City,District,Address,PostalCode;orderPayment:Type,Name,Code;orderShipment:No,Name,Code\" EagerLoad:\"order:orderItem,orderAddress,orderPayment,orderShipment\" VisitorId:10001 PlatformId:1

	preloadMap, eagerLoadMap := modelx.GetPreloadMap(in.Preload, in.EagerLoad)
	logx.Infof("preloadMap: %+v ", preloadMap)
	// preloadMap: map[order:[Id Sn OrderType TradeState Quantity GemAmount RetailAmount Freight DiscountAmount AdjustAmount ActualAmount Amount RefundAmount Gems TradeState Remark CreatedAt UpdatedAt PaidAt ShippedAt DeliveredAt ConfirmedAt ReviewedAt ClosedAt Comments Growth Integrals] orderAddress:[Consignee Mobile Province City District Address PostalCode] orderItem:[Id Sku ImageUrl ProductId EntryId Title Slug ProductType BrandId BrandTitle BrandSlug GemPrice RetailPrice Quantity Weight TradeState RefundAmount RefundQuantity] orderPayment:[Type Name Code] orderShipment:[No Name Code]]
	logx.Infof("eagerLoadMap: %+v ", eagerLoadMap)
	// eagerLoadMap: map[order:[orderItem orderAddress orderPayment orderShipment]]

	orderEntityName := model.RpcEntityNames.Order
	_, hasEntitySettings := model.RpcEntityPreloadMap[orderEntityName] // Order的关联字段
	if !hasEntitySettings {
		return &order.DetailResponse{}, nil
	}

	orderRepositoryName := model.RepositoryNames.Order
	columnMap, hasColumnMap := model.RepositoryPreloadMap[orderRepositoryName] // Order的数据库字段
	if !hasColumnMap {
		return &order.DetailResponse{}, nil
	}

	var selectCols []string
	if preloadFields, hasPreloadFields := preloadMap[orderEntityName]; hasPreloadFields {
		selectColMap := make(map[string]string)
		for _, field := range preloadFields {
			if _, exist := selectColMap[field]; !exist {
				if column, hasColumn := columnMap[field]; hasColumn {
					selectColMap[field] = column
				} else {
					selectColMap[field] = ""
				}
			}
		}
		for _, column := range selectColMap {
			if column != "" {
				selectCols = append(selectCols, column)
			}
		}
	}

	var filterMap map[string]map[string][]interface{}
	filterMap = modelx.GetFilterMap(in.Filter, columnMap)

	if filterMap == nil {
		filterMap = make(map[string]map[string][]interface{})
	}
	filterMap[model.OrderColumns.TradeState] = map[string][]interface{}{
		"moreThan": []interface{}{mqueuex.OrderTradeStateUserDeleted},
	}

	logx.Infof("filterMap: %+v ", filterMap)
	// filterMap: 

	orderList, _, err := l.svcCtx.Order.GetList(l.ctx, model.M{
		"pageSize": uint64(1),
		"select":   strings.Join(selectCols, ","),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	if len(orderList) == 0 {
		return nil, resultx.StatusError(resultx.ORDER_NOT_FOUND, "")
	}

	trade := orderList[0]
	if trade == nil {
		return &order.DetailResponse{}, nil
	}

	oid := trade.ID
	subRpcEntitySettingMap := make(map[string]map[string]*model.ColumnSetting)
	if eagerLoadRpcEntities, hasEagerLoadRpcEntities := eagerLoadMap[orderEntityName]; hasEagerLoadRpcEntities {
		for _, entity := range eagerLoadRpcEntities {
			if rpcEntitySettingMap, hasRpcEntitySettingMap := model.RpcEntityPreloadMap[entity]; hasRpcEntitySettingMap {
				subRpcEntitySettingMap[entity] = rpcEntitySettingMap
			}
		}
	}

	orderDiscountRpcEntityName := model.RpcEntityNames.OrderDiscount
	orderDiscountRepositoryName := model.RepositoryNames.OrderDiscount
	var orderDiscounts []*order.OrderDiscount
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[orderDiscountRpcEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[orderDiscountRpcEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[orderDiscountRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range preloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}

			orderDiscountFilterMap := make(map[string]map[string][]interface{})
			orderDiscountFilterMap[model.OrderDiscountColumns.OrderID] = map[string][]interface{}{
				"equalTo": []interface{}{oid},
			}
			orderDiscountList, _, err := l.svcCtx.Order.GetDiscountList(l.ctx, model.M{
				"select":   strings.Join(subSelectCols, ","),
			}, -1, orderDiscountFilterMap)
			if err != nil {
				return nil, err
			}

			if len(orderDiscountList) > 0 {
				for _, discount := range orderDiscountList {
					orderDiscounts = append(orderDiscounts, &order.OrderDiscount{
						Id: int64(discount.OrderDiscountID),
						OrderId: int64(discount.OrderID),
						GrouponAmount: int64(discount.GrouponAmount),
						WholesaleAmount: int64(discount.WholesaleAmount),
						CouponAmount: int64(discount.CouponAmount),
						PromotionAmount: int64(discount.ActivityAmount),
						IntegralAmount: int64(discount.IntegralAmount),
						DiscountAmount: int64(discount.DiscountAmount),
						Integrals: int64(discount.Integrals),
					})
				}
			}
		}
	}

	orderItemEntityName := model.RpcEntityNames.OrderItem
	orderItemRepositoryName := model.RepositoryNames.OrderItem
	var orderItems []*order.OrderItem
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[orderItemEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[orderItemEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[orderItemRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range preloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}
			orderItemFilterMap := make(map[string]map[string][]interface{})
			orderItemFilterMap[model.OrderItemColumns.OrderID] = map[string][]interface{}{
				"equalTo": []interface{}{oid},
			}
			itemList, _, err := l.svcCtx.Order.GetItemList(l.ctx, model.M{
				"select":  strings.Join(subSelectCols, ","),
			}, -1, orderItemFilterMap)
			if err != nil {
				return nil, err
			}

			if len(itemList) > 0 {
				for _, item := range itemList {
					orderItems = append(orderItems, &order.OrderItem{
						Id:             int64(item.OrderItemID),
						OrderId:        int64(item.OrderID),
						SkuId:          int64(item.SkuID),
						Sku:            item.Sku,
						ImageUrl:       item.SkuImageURL,
						ProductId:      int64(item.ProductID),
						EntryId:        int64(item.EntryID),
						Title:          item.Title,
						Slug:           item.Slug,
						ProductType:    int32(item.ProductType),
						BrandId:        int64(item.BrandID),
						BrandTitle:     item.BrandTitle,
						BrandSlug:      item.BrandSlug,
						GemPrice:       int64(item.GemPrice),
						RetailPrice:    int64(item.RetailPrice),
						Quantity:       int32(item.Quantity),
						Weight:         int64(item.Weight),
						TradeState:     int32(item.TradeState),
						Status:         int32(item.Status),
						GemAmount:      int64(item.GemAmount),
						RetailAmount:   int64(item.RetailAmount),
						Freight:        int64(item.Freight),
						DiscountAmount: int64(item.DiscountAmount),
						AdjustAmount:   int64(item.AdjustAmount),
						ActualAmount:   int64(item.ActualAmount),
						RefundAmount:   int64(item.RefundAmount),
						RefundQuantity: int32(item.RefundQuantity),
					})
				}
			}
		}
	}

	orderAddressEntityName := model.RpcEntityNames.OrderAddress
	orderAddressRepositoryName := model.RepositoryNames.OrderAddress
	var orderAddresses []*order.OrderAddress
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[orderAddressEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[orderAddressEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[orderAddressRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range preloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}
			orderAddressFilterMap := make(map[string]map[string][]interface{})
			orderAddressFilterMap[model.OrderAddressColumns.OrderID] = map[string][]interface{}{
				"equalTo": []interface{}{oid},
			}
			orderAddressFilterMap[model.OrderAddressColumns.Status] = map[string][]interface{}{ // 不查询删除的
				"moreThan": []interface{}{enumx.ObjectStatusPending},
			}
			addressList, _, err := l.svcCtx.Order.GetAddressList(l.ctx, model.M{
				"orderBy": model.OrderAddressColumns.OrderAddressID + " DESC",
				"pageSize": uint64(1),
				"select": strings.Join(subSelectCols, ","),
			}, -1, orderAddressFilterMap)
			if err != nil {
				return nil, err
			}

			if len(addressList) > 0 {
				for _, address := range addressList {
					orderAddresses = append(orderAddresses, &order.OrderAddress{
						Id:         int64(address.OrderAddressID),
						OrderId:    int64(address.OrderID),
						UserId:     int64(address.UserID),
						Consignee:  address.Consignee,
						Mobile:     address.Mobile,
						Province:   address.Province,
						City:       address.City,
						District:   address.District,
						Address:    address.DetailedAddress,
						PostalCode: address.PostalCode,
						RegionCode: address.RegionCode,
						Status:     int32(address.Status),
					})
				}
			}
		}
	}

	orderPaymentEntityName := model.RpcEntityNames.OrderPayment
	orderPaymentRepositoryName := model.RepositoryNames.OrderPayment
	var orderPayments []*order.OrderPayment
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[orderPaymentEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[orderPaymentEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[orderPaymentRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range preloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}
			orderPaymentFilterMap := make(map[string]map[string][]interface{})
			orderPaymentFilterMap[model.OrderPaymentColumns.OrderID] = map[string][]interface{}{
				"equalTo": []interface{}{oid},
			}
			orderPaymentFilterMap[model.OrderPaymentColumns.Status] = map[string][]interface{}{ // 不查询删除的
				"moreThan": []interface{}{enumx.ObjectStatusPending},
			}
			paymentList, _, err := l.svcCtx.Order.GetPaymentList(l.ctx, model.M{
				"orderBy": model.OrderPaymentColumns.OrderPaymentID + " DESC",
				"pageSize": uint64(1),
				"select":  strings.Join(subSelectCols, ","),
			}, -1, orderPaymentFilterMap)
			if err != nil {
				return nil, err
			}

			if len(paymentList) > 0 {
				for _, payment := range paymentList {
					orderPayments = append(orderPayments, &order.OrderPayment{
						Id:      int64(payment.OrderPaymentID),
						OrderId: int64(payment.OrderID),
						No:      payment.No,
						Amount:  int64(payment.Amount),
						Type:    int32(payment.Type),
						Name:    payment.Name,
						Code:    payment.Code,
						Status:  int32(payment.Status),
						PaidAt:  modelx.FormatNullDotTime(payment.PaidAt, ""),
					})
				}
			}
		}
	}

	orderShipmentEntityName := model.RpcEntityNames.OrderShipment
	orderShipmentRepositoryName := model.RepositoryNames.OrderShipment
	var orderShipments []*order.OrderShipment
	if _, hasRpcEntitySettingMap := subRpcEntitySettingMap[orderShipmentEntityName]; hasRpcEntitySettingMap {
		preloadFields, hasPreloadFields := preloadMap[orderShipmentEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[orderShipmentRepositoryName]
		if hasPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range preloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}
			orderShipmentFilterMap := make(map[string]map[string][]interface{})
			orderShipmentFilterMap[model.OrderShipmentColumns.OrderID] = map[string][]interface{}{
				"equalTo": []interface{}{oid},
			}
			orderShipmentFilterMap[model.OrderShipmentColumns.Status] = map[string][]interface{}{ // 不查询删除的
				"moreThan": []interface{}{enumx.ObjectStatusPending},
			}
			itemList, _, err := l.svcCtx.Order.GetShipmentList(l.ctx, model.M{
				"orderBy": model.OrderShipmentColumns.OrderShipmentID + " DESC",
				"select":  strings.Join(subSelectCols, ","),
			}, -1, orderShipmentFilterMap)
			if err != nil {
				return nil, err
			}

			if len(itemList) > 0 {
				for _, item := range itemList {
					orderShipments = append(orderShipments, &order.OrderShipment{
						Id:        int64(item.OrderShipmentID),
						OrderId:   int64(item.OrderID),
						No:        item.No,
						Type:      int32(item.Type),
						Name:      item.Name,
						Code:      item.Code,
						Status:    int32(item.Status),
						UpdatedAt: modelx.FormatTime(item.UpdatedAt, ""),
					})
				}
			}
		}
	}

	return &order.DetailResponse{
		Id:              int64(trade.ID),
		ParentId:        int64(trade.ParentID),
		UserId:          int64(trade.UserID),
		Buyer:           trade.Buyer,
		Sn:              trade.OrderSN,
		OrderType:       int32(trade.OrderType),
		SourceType:      int32(trade.SourceType),
		Quantity:        int32(trade.Quantity),
		GemAmount:       int64(trade.GemAmount),
		RetailAmount:    int64(trade.RetailAmount),
		Freight:         int64(trade.Freight),
		DiscountAmount:  int64(trade.DiscountAmount),
		AdjustAmount:    int64(trade.AdjustAmount),
		ActualAmount:    int64(trade.ActualAmount),
		DepositAmount:   int64(trade.DepositAmount),
		BalanceAmount:   int64(trade.BalanceAmount),
		Amount:          int64(trade.RemainingAmount),
		RefundAmount:    int64(trade.RefundAmount),
		Gems:            int64(trade.Gems),
		TradeState:      int32(trade.TradeState),
		DelState:        int32(trade.DelState),
		Remark:          trade.Remark,
		SellerMemo:      trade.SellerMemo,
		CreatedAt:       modelx.FormatTime(trade.CreatedAt, ""),
		UpdatedAt:       modelx.FormatTime(trade.UpdatedAt, ""),
		DeletedAt:       modelx.FormatNullDotTime(trade.DeletedAt, ""),
		PaidAt:          modelx.FormatNullDotTime(trade.PaidAt, ""),
		ShippedAt:       modelx.FormatNullDotTime(trade.ShippedAt, ""),
		DeliveredAt:     modelx.FormatNullDotTime(trade.DeliveredAt, ""),
		ConfirmedAt:     modelx.FormatNullDotTime(trade.ConfirmedAt, ""),
		ReviewedAt:      modelx.FormatNullDotTime(trade.ReviewedAt, ""),
		FulfilledAt:     modelx.FormatNullDotTime(trade.FulfilledAt, ""),
		ClosedAt:        modelx.FormatNullDotTime(trade.ClosedAt, ""),
		AutoComfirmDays: int32(trade.AutoComfirmDays),
		Comments:        int32(trade.Comments),
		Growth:          int32(trade.Growth),
		Integrals:       int32(trade.Integrals),
		Discounts:       orderDiscounts,
		Items:           orderItems,
		Addresses:       orderAddresses,
		Payments:        orderPayments,
		Shipments:       orderShipments,
	}, nil
}

